package br.ufpe.cin.mac.parser.xml;

import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.List;

import org.jdom.Content;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import br.ufpe.cin.mac.parser.Binds;
import br.ufpe.cin.mac.parser.CanonicalElements;
import br.ufpe.cin.mac.parser.XBind;
import br.ufpe.cin.mac.parser.XComponent;
import br.ufpe.cin.mac.parser.XConnector;
import br.ufpe.cin.mac.parser.XMiddleware;

public class XmlWriter {

	private XMiddleware mid;

	private FileOutputStream xml;

	public XmlWriter() {
	
	}

	public void writeXML(XMiddleware mid, String out) {
	
		if (mid == null)
			return;

		try {
			this.mid = mid;
			this.xml = new FileOutputStream(out);
			Element xMiddleware = readXMiddleware();

			Document doc = new Document();
			doc.setRootElement(xMiddleware);

			Format format = Format.getPrettyFormat();
			format.setLineSeparator("\n");
			XMLOutputter xmlOut = new XMLOutputter(format);

			xmlOut.output(doc, this.xml);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private Element readXMiddleware() {
		Element xMiddleware = new Element(mid.tagName);

		xMiddleware.setAttribute("id", mid.getId());

		xMiddleware.addContent(readCanonicalElement());
		xMiddleware.addContent(readBinds());

		return xMiddleware;
	}

	private Content readBinds() {
		Binds b = mid.getBinds();
		List<XBind> xBinds = b.getBinds();

		Element binds = new Element(b.tagName);
		Element xBind;

		Iterator<XBind> ibind = xBinds.iterator();
		while (ibind.hasNext()) {
			XBind bind = ibind.next();
			xBind = new Element(bind.tagName);
			xBind.setAttribute("id", bind.getId());
			xBind.setAttribute("to", bind.getTo());
			xBind.setAttribute("from", bind.getFrom());
			xBind.setAttribute("through", bind.getThrough());

			binds.addContent(xBind);
		}

		return binds;
	}

	private Element readCanonicalElement() {
		CanonicalElements elements = mid.getCanonicalElements();
		List<XComponent> components = elements.getXComponents();
		List<XConnector> connectors = elements.getXConnectors();

		Element canonical = new Element(elements.TAG_NAME);
		Element xComponent, xConnector, concreteConnector;
		XComponent component;
		XConnector connector;

		// Load Components
		Iterator<XComponent> icomp = components.iterator();
		while (icomp.hasNext()) {
			component = icomp.next();
			xComponent = new Element(component.tagName);
			xComponent.setAttribute("id", component.getId());
			xComponent.setAttribute("name", component.getName());
			// Adiciona ao canonical o elemento Component criado
			canonical.addContent(xComponent);
		}

		// Load Connectors
		Iterator<XConnector> iconn = connectors.iterator();
		while (iconn.hasNext()) {
			connector = iconn.next();
			xConnector = new Element(connector.TAG_NAME);
			xConnector.setAttribute("id", connector.getId());
			xConnector.setAttribute("name", connector.getName());
			// Adiciona ao canonical o elemento Connector criado
			canonical.addContent(xConnector);
		}

		connector = elements.getConcreteConnector();

		concreteConnector = new Element(connector.TAG_NAME_CONCRETE);

		concreteConnector.setAttribute("id", connector.getId());
		concreteConnector.setAttribute("name", connector.getName());
		canonical.addContent(concreteConnector);

		return canonical;
	}
}
